
import {login,logout,getInfo,refreshToken} from '@/api/user'
import {getToken,setToken,removeToken} from '@/utils/auth'
import {resetRouter,asyncRoutes,constantRoutes,anyRoutes} from '@/router'
import router from '@/router'
import { Message } from 'element-ui'
/**
 * 使用meta.codes确定当前用户是否有权限
 * @param rolesArr
 * @param route
 */
function hasPermission(rolesArr, route) {

  if (route.meta && route.meta.codes) {
    if(rolesArr.includes(route.meta.codes)){
      return true
    }else{
      return false
    }
    
    
  } else {
    return true
  }
}

/**
 * 递归过滤异步路由表
 * @param routes asyncRoutes
 * @param rolesArr
 */
export function filterAsyncRoutes(routes, rolesArr) {
  const res = []
  routes.forEach(route => {
    const tmp = { ...route }
    if (hasPermission(rolesArr, tmp)) {
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, rolesArr)
      }
      res.push(tmp)
    }
  })

  return res
}

const getDefaultState = () => {
  return {

    // 获取token
    token: getToken(),
    // 获取refresh
    refreshToken: getToken('refresh'),
    // 用户名
    name: '',
    // 用户邮箱
    email: '',
    // 用户手机号
    mobile: '',
    // 用户头像
    avatar: '',
    // 是否超级管理员
    is_superuser: 0,
    // 图片域名
    img_domain: '',
    // 服务器返回的菜单信息，根据不同的角色返回的标记信息，数组里边的元素是字符串
    routes: [],
    // 角色信息 更改角色权限时如果是当前用户所在组的就刷新页面
    roles: [],
    // 按钮权限信息
    buttons: [],
    // 对比之后[项目中已有的异步路由,与服务器返回的标记信息进行对比最终要展示的路由]
    resultAsyncRoutes: [],
    // 用户最终需要展示的全部路由
    resultAllRoutes: []
  }
}

const state = getDefaultState()

const mutations = {
  RESET_STATE: (state) => {
    Object.assign(state, getDefaultState())
  },
  SET_TOKEN: (state, token) => {
    state.token = token
  },
  SET_REFRESH_TOKEN: (state, refresh) => {
    state.refreshToken = refresh
  },
  SET_NAME: (state, name) => {
    state.name = name
  },
  SET_AVATAR: (state, avatar) => {
    state.avatar = avatar
  },
  SET_ROLES: (state, roles) => {
    state.roles = roles
  },
  // 存储用信息
  SET_USERINFO: (state, userInfo) => {
    // 用户名
    state.name = userInfo.username
    // 头像
    state.avatar = userInfo.avatar
    // email
    state.email = userInfo.email
    // 电话号
    state.mobile = userInfo.mobile
    // token
    state.token = userInfo.token
    // 重新获取token的token
    state.refreshToken = userInfo.refresh
    // 是否是超级管理员
    state.is_superuser = userInfo.is_superuser ? 1 : 0
    // 图片域名
    state.img_domain = userInfo.img_domain ? userInfo.img_domain : env.VUE_APP_BASE_API
    // 菜单权限
    state.routes = userInfo.routes
    // 按钮权限
    state.buttons = userInfo.buttons ? userInfo.buttons : []
    // 角色信息
    state.roles = userInfo.roles
  },

  SET_ROUTES: (state, routes) => {
    state.resultAsyncRoutes = routes
    state.resultAllRoutes = constantRoutes.concat(routes,anyRoutes)
  }
}

const actions = {
  
  async login({commit}, userInfo) {
    const {username,password} = userInfo

    let result = await login({username: username.trim(),password: password})

    if (result.code == 200) {

      // commit('SET_USERINFO', result.data)

      setToken(result.data.token, 'token')
      setToken(result.data.refresh, 'refresh')
      commit('SET_TOKEN', result.data.token)
      commit('SET_REFRESH_TOKEN', result.data.refresh)
      return 'ok'
    } else {
      return Promise.reject(new Error('faile'))
    }
  },

  // get user info
  getInfo({ commit, state }) {
    return new Promise((resolve, reject) => {
      getInfo().then(response => {
        const { data } = response

        if (!data) {
          reject('验证失败，请重新登录')
        }
        
        const { routes, is_superuser } = data

        let accessedRoutes

        if(data.is_superuser){
          accessedRoutes = asyncRoutes
          
        }else{
          if (!routes || routes.length <= 0) {
            reject('没有指定任何权限！')
          }else{
            accessedRoutes = filterAsyncRoutes(asyncRoutes, routes)
          }
          
        }
        
      

        data.token = state.token
        data.refresh = state.refreshToken
        commit('SET_USERINFO', data)
        commit('SET_ROUTES', accessedRoutes)
        resolve(accessedRoutes)
      }).catch(error => {
        reject(error)
      })
    })
  },

  // 退出登陆
  logout({ commit, state }) {
    return new Promise((resolve, reject) => {
      logout().then(() => {
        removeToken() // must remove  token  first
        resetRouter()
        commit('RESET_STATE')
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  // 重新获取token
  async refreshToken({commit,state}){

    
    return new Promise((resolve, reject) => {
      refreshToken({refresh: state.refreshToken}).then(response => {
        const { data } = response

        if (!data) {
          reject('验证失败，请重新登录')
        }
        commit('SET_TOKEN', data.access)
        setToken(data.access, 'token')
        resolve(data)
      }).catch(error => {
        const {response} = error; // 获取错误响应对象

        let errorMsg = response.status === 401 ? "登陆已过期，请重新登陆！" : "未知错误，请重新登陆！"
        Message({
          message: errorMsg,
          type: 'error',
          duration: 5 * 1000
        })
        // 遇到错误注销token信息重新登陆
        
        removeToken()
        resetRouter()
        commit('RESET_STATE')
        router.push('/login?redirect=' + router.currentRoute.path);
        reject(error)
      })
    })
  },

  // remove token
  resetToken({ commit }) {
    return new Promise(resolve => {
      removeToken() // must remove  token  first
      commit('RESET_STATE')
      resolve()
    })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

